//Limit1: at-inst collection capacity is AT_ISA_CAPACITY(out is reserved), so one byte length is enough to represent it
//Limit2: inst excution list max include 256(include at-inst and ex-inst) items, less is ok but more is forbidden
#ifndef _ATE_H
#define _ATE_H
#include "apt32f003.h"

/*close this defines when make lib in future*/
#define INSTRUCT_CODE_CAPACITY	255
#define AT_ISA_CAPACITY	INSTRUCT_CODE_CAPACITY-3

#define EX_PWR_KEY	INSTRUCT_CODE_CAPACITY
#define EX_JUMPTO	INSTRUCT_CODE_CAPACITY - 1

/*def inst struct*/
typedef struct {
	uint8_t id;
	uint8_t timeout;
	uint8_t errreps; //get error info then repeat, not mean repeat after timeout 
	uint8_t errdest; //single error(timeout is a kind of error, so goto dest when timeout happen) jump, fit AType_0/AType_I/AType_II
} AT_SYNC_T;

//#define TIMEOUT(n) (n<<8)
//#define ERROR_RETRY_TIMES(n) (n<<16)
//#define ERR_JUMPTO(n) (n<<24)
#define TIMEOUT(n) (n)
#define ERROR_RETRY_TIMES(n) (n)
#define ERR_JUMPTO(n) (n)

typedef struct {
	uint8_t id;
	uint8_t timeout;
	uint8_t errreps;
	uint8_t errasst; //multiply error jump, fit AType_III and above
} AT_ASYN_T;


typedef struct {
	uint8_t id;
	uint8_t dest;
	uint16_t delayms;
} EX_JUMP_T;

#define ABS_ADDR(n) (n<<8)
#define MS_DELAY(n) (n<<16)


typedef struct {
	uint8_t id;
	uint8_t predrp;
	uint8_t indrop;
	uint8_t aftdrp;
} EX_PWR_KEY_T;

#define PRE_DELAY(n) (n<<8)
#define DROP_HOLD(n) (n<<16)
#define AFT_DELAY(n) (n<<24)


typedef union {
	AT_SYNC_T atsync;
	AT_ASYN_T atasyn;
	EX_JUMP_T exjump;
	EX_PWR_KEY_T expwrkey;
	uint32_t inst;
} INST_T;

typedef struct {
	uint32_t seg_inf;
	const uint8_t * seg_str;
} AT_FRAME_T;


typedef uint32_t (*AT_MSG_CALLBACK)(uint32_t* ctx, uint32_t msg);

void reg_loop_func(void (*func)(uint32_t ctx));
void reg_new_at(uint8_t inst, AT_MSG_CALLBACK atmcb);
void reg_at_meta(uint8_t msgid, uint8_t msize, uint16_t ssize, const uint8_t * string);
void ate_loop(void);

uint32_t uart_send_push_nbytes(uint8_t * data, uint32_t n);
void clearInSending(void);
int uart_send_pop_byte(uint8_t * data);
int uart_recv_push_byte(uint8_t data);
int uart_recv_pop_byte(uint8_t * data);

#endif